<?php

namespace app\common\model;

use think\facade\Cache;
use think\facade\Db;
use think\Model;
use think\model\concern\SoftDelete;

class BaseModel extends Model
{
    protected $autoWriteTimestamp = true;
    /**
     * @param array $where 查询条件
     * @param string $sort 排序方式
     * @param bool $page 是否分页
     * @return array
     */
    public function getList($where = [], $sort = 'id desc', $page = true)
    {
        $query = $this->formatQuery($where);
        if ($page) {
            $query->page(PAGE, LIMIT);
        }
        $res = $query->order($sort)->column($this->getPk());
        $list = [];
        if ($res) {
            foreach ($res as $v) {
                $list[] = $this->getInfo($v);
            }
        }
        return $list;
    }

    public function getInfo($id)
    {
        $cacheKey = $this->getCacheKey($id);
        $data = $this->getCache($cacheKey);
        if (!$data) {
            $data = $this->find($id);
            $this->setCache($cacheKey, $data);
        }
        return $data;
    }
    public function edit($data)
    {
        $id = isset($data[$this->getPk()]) ? (int)$data[$this->getPk()] : 0;
        $this->formatData($data, $id);
        if ($id) {
            unset($data[$this->getPk()]);
            $data['update_time'] = time();
            $this->update($data, [$this->getPk() => $id]);
            $cache_key = $this->getCacheKey($id);
            $this->removeCache($cache_key);
            $row_id = $id;
        } else {
            $data['create_time'] = time();
            $row_id = $this->insertGetId($data);
        }
        return $row_id;
    }

    /**
     * @param $ids 数据id
     * @param false $force
     */
    public function deleteAll($ids,$force = false){
        foreach ($ids as $v){
            if($force){
                $res = $this->where($this->getPk(),$v)->delete();
            }else{
                $res = $this->where($this->getPk(),$v)->data(['delete_time' => time()])->save();
            }
            if($res) {
                //删除缓存
                $this->removeCache($this->getCacheKey($v));
            }
        }
    }

    private function formatQuery($where = [])
    {
        return $this->where($where)->whereNull('delete_time');
    }

    //判断数据库中是否存在该表
    public function tableExists($table)
    {
        $tables = $this->getTableList();
        if (strpos($table, env('database.prefix')) === false) {
            $table = env('database.prefix') . $table;
        }
        return in_array($table, $tables) ? true : false;
    }

    //获取数据库所有表
    public function getTableList()
    {
        $tables = [];
        $database = strtolower(env('database.database'));
        $data = Db::query("SHOW TABLES");
        foreach ($data as $v) {
            $tables[] = $v["Tables_in_{$database}"];
        }
        return $tables;
    }

    private function getTableFieldsList($table = '')
    {
        $table = $table ?: $this->getTable();
        $field_list = Db::query("SHOW FIELDS FROM {$table}");
        $info_list = [];

        foreach ($field_list as $row) {
            if ((strpos($row['Type'], "int") === false) || (strpos($row['Type'], "bigint") !== false)) {

                $type = "string";
                $default = $row['Default'] ?: "";
            } else {
                $type = "int";
                $default = (int)$row['Default'] ?: 0;
            }
            $info_list[$row['Field']] = array(
                'Type' => $type,
                'Default' => $default
            );
        }
        return $info_list;
    }

    /**
     * 格式化表数据
     * @param array $data 数据源
     * @param int $id 记录ID
     * @param string $table 表字段数据
     * @return array 返回结果
     * @throws \think\db\exception\BindParamException
     * @throws \think\exception\PDOException
     */
    protected function formatData(&$data = [], $id = 0, $table = '')
    {
        $data_list = [];
        $tables = $table ? explode(",", $table) : array($this->getTable());
        $item_data = [];
        foreach ($tables as $table) {
            $temp_data = [];
            $table_fields_list = $this->getTableFieldsList($table);
            foreach ($table_fields_list as $field => $field_info) {
                if ($field == "id") {
                    continue;
                }
                // 强制类型转换
                if (isset($data[$field])) {
                    if ($field_info['Type'] == "int") {
                        $item_data[$field] = (int)$data[$field];
                    } else {
                        $item_data[$field] = (string)$data[$field];
                    }
                }

                if (!isset($data[$field]) && in_array($field, array('update_time', 'create_time','delete_time'))) {
                    continue;
                }
                // 插入数据-设置默认值
                if (!$id && !isset($data[$field])) {
                    $item_data[$field] = $field_info['Default'];
                }
                if (isset($item_data[$field])) {
                    $temp_data[$field] = $item_data[$field];
                }
            }
            $data_list[] = $temp_data;
        }
        $data = $item_data;
        return $data_list;
    }

    /**
     * 获取缓存 key
     * @return string
     */
    private function getCacheKey()
    {
        $args = func_get_args();
        if ($this->name) {
            array_unshift($args, $this->name);
        }
        return implode('_', $args);
    }

    /**
     * 设置缓存
     * @param $key
     * @param $data
     * @param int $ttl
     * @return bool|void
     */
    public function setCache($key, $data, $ttl = 0)
    {
        if (!$data) {
            return Cache::set($key, null);
        }
        $gzcompress_data = gzcompress(json_encode($data));
        return Cache::set($key, $gzcompress_data);
    }

    /**
     * 获取缓存
     * @param $key
     * @return mixed
     */
    public function getCache($key)
    {
        $data = Cache::get($key);
        if ($data) {
            $data = json_decode(gzuncompress($data), true);
        }
        return $data;
    }

    public function resetCache($id, $data = [], $is_edit = 0)
    {
        $info = [];
        if ($is_edit) {
            $info = $this->getInfo($id);
        }
        if (is_array($data)) {
            $info = array_merge($info, $data);
        } else {
            $info = $data;
        }
        $cacheKey = $this->getCacheKey($id);
        $this->setCache($cacheKey, $info);
    }

    /**
     * 删除缓存
     * @param $key
     * @return bool
     */
    public function removeCache($key)
    {
        if (Cache::has($key)) {
            return Cache::delete($key);
        }
        return false;
    }

}